home *** CD-ROM | disk | FTP | other *** search
- /* TCP control and status routines
- * Copyright 1991 Phil Karn, KA9Q
- *
- * Mods by G1EMM
- * Mods by WG7J
- * Mods by WA3DSP
- * Mods by PA0GRI
- * Copyright 1992 Gerard J van der Grinten, PA0GRI
- */
- #include "global.h"
- #include "ctype.h"
- #include "commands.h"
- #ifdef MSDOS
- #include "socket.h"
- #else
- #include "timer.h"
- #include "mbuf.h"
- #endif
- #include "netuser.h"
- #include "internet.h"
- #include "iface.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: tcpcmd.c,v 1.21 1997/09/07 00:31:16 root Exp root $";
- #endif
-
- #ifdef TCPACCESS
- static int doaccess (int argc, char *argv[], void *p);
- #endif
-
- #if defined(TCPACCESS) || defined(UDPACCESS)
- int do_tcpudp_access (int argc, char *argv[], void *p);
- static void addtaccess (struct rtaccess **tpacc, uint32 target, unsigned int bits, int16 low, int16 high, int16 permit);
- #endif
-
- static int tcpirtt (int argc, char *argv[], void *p);
- static int dotcpirtt (int argc, char *argv[], void *p);
- static int tcpmss (int argc, char *argv[], void *p);
- static int dotcpmss (int argc, char *argv[], void *p);
- static int dortt (int argc, char *argv[], void *p);
- static int dotcpclean (int argc, char *argv[], void *p);
- static int dotcpkick (int argc, char *argv[], void *p);
- static int dotcpreset (int argc, char *argv[], void *p);
- static int dotcpretries (int argc, char *argv[], void *p);
- static int tcpretries (int argc, char *argv[], void *p);
- static int dotcpstat (int argc, char *argv[], void *p);
- static int dotcpconnect (int argc, char *argv[], void *p);
- static int dotcptimer (int argc, char *argv[], void *p);
- static int tcptimer (int argc, char *argv[], void *p);
- static int dotcptr (int argc, char *argv[], void *p);
- static int dotcpwindow (int argc, char *argv[], void *p);
- static int tcpwindow (int argc, char *argv[], void *p);
- static int dotcpmaxwait (int argc, char *argv[], void *p);
- static int tcpmaxwait (int argc, char *argv[], void *p);
- static int dotcpsyndata (int argc, char *argv[], void *p);
- static int tcpsyndata (int argc, char *argv[], void *p);
- int dotcpview (int argc, char *argv[], void *p);
- static int dotcpblimit (int argc, char *argv[], void *p);
- static int tcpblimit (int argc, char *argv[], void *p);
- static void rxtx_data_compute (struct tcb * tcb, int32 * sent, int32 * recvd);
- static int tstat (int flag);
- static int tstat2 (int flag);
-
- #ifdef TCPACCESS
- struct rtaccess *TCPaccess = NULLACCESS; /* access list */
- #endif
- extern int tcptimertype;
- extern long Tcp_maxwait;
- extern int Tcp_blimit;
-
-
- #ifdef CATALOG
- #include "catalog.h"
-
- #define CAT tcpcmd_catalog
-
- #define tracingstr __STR(0)
- #define irttstr __STR(1)
- #define irttdisp __STR(2)
- #define mssstr __STR(3)
- #define windowstr __STR(4)
- #define syndatastr __STR(5)
- #define retriesstr __STR(6)
- #define maxwaitstr __STR(7)
- #define backoffstr __STR(8)
- #define cbheader __STR(9)
- #define reassembly __STR(10)
- #define reassstr __STR(11)
- #define retrying __STR(12)
- #define backoffval __STR(13)
- #define timerstopped __STR(14)
- #define timerrunning __STR(15)
- #define timerexp __STR(16)
- #define rttval __STR(17)
- #define viewsyntax __STR(18)
- #define viewhdr1 __STR(19)
- #define viewhdr2 __STR(20)
- #define timeris __STR(21)
- #define timertypesyntax __STR(22)
- #define accesshdr __STR(23)
- #define accesssyntax __STR(24)
- #define notfound __STR(25)
-
- #else /* CATALOG */
- static const char tracingstr[] = "TCP state tracing";
- static const char irttstr[] = "TCP default irtt";
- static const char irttdisp[] = "%s: srtt %lu mdev %lu\n";
- static const char mssstr[] = "TCP MSS";
- static const char windowstr[] = "TCP window";
- static const char syndatastr[] = "TCP syn+data piggybacking";
- static const char retriesstr[] = "max. retries";
- static const char maxwaitstr[] = "max. retry wait (ms)";
- static const char backoffstr[] = "backoff limit";
- static const char cbheader[] = " Init seq Unack Next Resent CWind Thrsh Wind MSS Queue Total\nSend:";
- static const char reassembly[] = "Reassembly queue:\n";
- static const char reassstr[] = " seq x%lx %u bytes\n";
- static const char retrying[] = "Retrying ";
- static const char backoffval[] = "Backoff %u ";
- static const char timerstopped[] = "Timer stopped ";
- static const char timerrunning[] = "Timer running (%ld/%ld ms) ";
- static const char timerexp[] = "Timer expired ";
- static const char rttval[] = "SRTT %ld ms Mean dev %ld ms\n";
- static const char viewsyntax[] = "Use: tcp view <bytes|timers>\n";
- static const char viewhdr1[] = " Send Send Receive Receive\nRemote Socket:Port:Local Port/State TCB Bytes Retries Bytes Retries\n";
- static const char viewhdr2[] = "Remote Socket:Port:Local Port/State TCB Boff State Timer SRTT\n";
- static const char timeris[] = "Tcp timer type is %s\n";
- static const char timertypesyntax[] = "use: tcp timertype [linear|exponential]\n";
- static const char accesshdr[] = "IP Address Mask Low Port High Port State\n";
- static const char accesssyntax[] = " Format: tcp access <permit|deny|delete> <dest addr>[/<bits>] [lowport [highport]]\n";
- static const char notfound[] = "Not found.\n";
-
- #endif /* CATALOG */
-
- static const char tstat2hdr[] =
- #if !defined(TNOS_68K) && !defined(UNIX)
- "&TCB Rcv-Q Snd-Q Local socket Remote socket State\n";
- #else
- "&TCB Rcv-Q Snd-Q Local socket Remote socket State\n";
- #endif
-
- static const char tstat2fmt[] =
- #if !defined(TNOS_68K) && !defined(UNIX)
- "%4.4x%6u%6u ";
- #else
- "%-8.8lx%6u%6u ";
- #endif
-
- static const char str23[] = "%-23s";
- static const char tstatmib[] = "(%2u)%-20s%10lu";
- static const char str9lx[] = "%9lx";
- static const char str6u[] = "%6u";
- static const char spaces6[] = " ";
- static const char spaces5[] = " ";
- static const char linearstr[] = "linear";
- static const char exponentialstr[] = "exponential";
- static const char permitstr[] = "permit";
- static const char denystr[] = "deny";
- static const char allstr[] = "all";
- static const char deletestr[] = "delete";
- static const char viewretrystr[] = " Retry ";
- static const char viewtrystr[] = " Try ";
- static const char viewstopped[] = " Stopped";
- static const char viewrun[] = " Run (";
- static const char view9999[] = ">9999/9999)s";
- static const char viewexp[] = " Expired";
-
-
- /* TCP subcommand table */
- static struct cmds Tcpcmds[] =
- {
- #ifdef TCPACCESS
- { "access", doaccess, 0, 0, NULLCHAR},
- #endif
- { "blimit", dotcpblimit, 0, 0, NULLCHAR},
- { "connections", dotcpconnect, 0, 0, NULLCHAR},
- { "clean", dotcpclean, 0, 0, NULLCHAR},
- { "irtt", dotcpirtt, 0, 0, NULLCHAR},
- { "kick", dotcpkick, 0, 2, "tcp kick <tcb>"},
- { "maxwait", dotcpmaxwait, 0, 0, NULLCHAR},
- { "mss", dotcpmss, 0, 0, NULLCHAR},
- { "reset", dotcpreset, 0, 2, "tcp reset <tcb>"},
- { "retries", dotcpretries, 0, 0, NULLCHAR},
- { "rtt", dortt, 0, 3, "tcp rtt <tcb> <val>"},
- { "status", dotcpstat, 0, 0, NULLCHAR},
- { "syndata", dotcpsyndata, 0, 0, NULLCHAR},
- { "timertype", dotcptimer, 0, 0, NULLCHAR},
- { "trace", dotcptr, 0, 0, NULLCHAR},
- { "view", dotcpview, 0, 0, NULLCHAR},
- { "window", dotcpwindow, 0, 0, NULLCHAR},
- { NULLCHAR, NULL, 0, 0, NULLCHAR}
- };
-
-
- int
- dotcp (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return subcmd (Tcpcmds, argc, argv, p);
- }
-
-
- static int
- dotcptr (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return setbool (&Tcp_trace, tracingstr, argc, argv);
- }
-
-
- /* Reset lingering FIN Wait 2 state connections */
- static int
- dotcpclean (argc, argv, p)
- int argc OPTIONAL;
- char *argv[] OPTIONAL;
- void *p OPTIONAL;
- {
- struct tcb *tcb;
-
- for (tcb = Tcbs; tcb != NULLTCB; tcb = tcb->next) {
- if (tcb->state == TCP_FINWAIT2) {
- reset_tcp (tcb);
- tcb = Tcbs; /* start at the top again */
- }
- }
- return 0;
- }
-
-
- /* Eliminate a TCP connection */
- static int
- dotcpreset (argc, argv, p)
- int argc OPTIONAL;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct tcb *tcb;
-
- tcb = (struct tcb *) htoi (argv[1]);
- if (!tcpval (tcb)) {
- tputs (Notval);
- return 1;
- }
- reset_tcp (tcb);
- return 0;
- }
-
-
- /* Set initial round trip time for new connections */
- static int
- tcpirtt (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setlong ((long *) p, irttstr, argc, argv);
- }
-
-
- static int
- dotcpirtt (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- struct tcp_rtt *tp;
-
- (void) tcpirtt (argc, argv, (void *) &Tcp_irtt);
- if (argc < 2) {
- for (tp = &Tcp_rtt[0]; tp < &Tcp_rtt[RTTCACHE]; tp++) {
- if (tp->addr != 0) {
- if (tprintf (irttdisp, inet_ntoa (tp->addr), tp->srtt, tp->mdev) == EOF)
- break;
- }
- }
- }
- return 0;
- }
-
-
- /* Set smoothed round trip time for specified TCB */
- static int
- dortt (argc, argv, p)
- int argc OPTIONAL;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct tcb *tcb;
-
- tcb = (struct tcb *) htoi (argv[1]);
- if (!tcpval (tcb)) {
- tputs (Notval);
- return 1;
- }
- tcb->srtt = atol (argv[2]);
- return 0;
- }
-
-
- /* Force a retransmission */
- static int
- dotcpkick (argc, argv, p)
- int argc OPTIONAL;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct tcb *tcb;
-
- tcb = (struct tcb *) htoi (argv[1]);
- if (kick_tcp (tcb) == -1) {
- tputs (Notval);
- return 1;
- }
- return 0;
- }
-
-
- /* Set default maximum segment size */
- static int
- tcpmss (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort ((unsigned short *) p, mssstr, argc, argv);
- }
-
-
- static int
- dotcpmss (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return tcpmss (argc, argv, (void *) &Tcp_mss);
- }
-
-
- /* Set default window size */
- static int
- tcpwindow (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setshort ((unsigned short *) p, windowstr, argc, argv);
- }
-
-
- static int
- dotcpwindow (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return tcpwindow (argc, argv, (void *) &Tcp_window);
- }
-
-
- static int
- tcpsyndata (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool ((int *) p, syndatastr, argc, argv);
- }
-
-
- static int
- dotcpsyndata (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return tcpsyndata (argc, argv, (void *) &Tcp_syndata);
- }
-
-
- /* Set maximum number of backoffs before resetting the connection */
- static int
- tcpretries (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setint ((int *) p, retriesstr, argc, argv);
- }
-
-
- static int
- dotcpretries (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return tcpretries (argc, argv, (void *) &Tcp_retries);
- }
-
-
- /* Set maximum retry waittime in ms. */
- static int
- tcpmaxwait (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setlong ((long *) p, maxwaitstr, argc, argv);
- }
-
-
- static int
- dotcpmaxwait (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return tcpmaxwait (argc, argv, (void *) &Tcp_maxwait);
- }
-
-
- /* Set backoff limit on the connection; from N1BEE */
- static int
- tcpblimit (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- return setint ((int *) p, backoffstr, argc, argv);
- }
-
-
- static int
- dotcpblimit (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return tcpblimit (argc, argv, (void *) &Tcp_blimit);
- }
-
-
- /* Display status of TCBs */
- static int
- dotcpconnect (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct tcb *tcb;
-
- if (argc < 2)
- (void) tstat2 (0);
- else {
- if (toupper (argv[1][0]) == 'A')
- (void) tstat (1);
- else {
- tcb = (struct tcb *) htoi (argv[1]);
- if (!tcpval (tcb))
- tputs (Notval);
- else
- st_tcp (tcb);
- }
- }
- return 0;
- }
-
-
- /* Display status of TCBs with MIB info*/
- static int
- dotcpstat (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct tcb *tcb;
-
- if (argc < 2)
- (void) tstat (0);
- else {
- if (toupper (argv[1][0]) == 'A')
- (void) tstat (1);
- else {
- tcb = (struct tcb *) htoi (argv[1]);
- if (!tcpval (tcb))
- tputs (Notval);
- else
- st_tcp (tcb);
- }
- }
- return 0;
- }
-
-
- /* Dump TCP stats and summary of all TCBs
- * &TCB Rcv-Q Snd-Q Local socket Remote socket State
- * 1234 0 0 xxx.xxx.xxx.xxx:xxxxx xxx.xxx.xxx.xxx:xxxxx Established
- * Dump display for TNOS_68K and UNIX
- * &TCB Rcv-Q Snd-Q Local socket Remote socket State
- * 123456 0 0 xxx.xxx.xxx.xxx:xxxxx xxx.xxx.xxx.xxx:xxxxx Established
- */
- static int
- tstat2 (int flag)
- {
- register struct tcb *tcb;
-
- tputs (tstat2hdr);
- for (tcb = Tcbs; tcb != NULLTCB; tcb = tcb->next) {
- if (tcb->state == TCP_LISTEN && !flag)
- continue;
- tprintf (tstat2fmt, tcb, tcb->rcvcnt, tcb->sndcnt);
- tprintf (str23, pinet (&tcb->conn.local));
- tprintf (str23, pinet (&tcb->conn.remote));
- tprintf ("%-s", Tcpstates[(int) tcb->state]);
- if (tcb->state == TCP_LISTEN && tcb->flags.clone)
- tputs (" (S)");
- if (tputc ('\n') == EOF)
- return 0;
- }
- return 0;
- }
-
-
- static int
- tstat (int flag)
- {
- register int i;
- int j;
-
- for (j = i = 1; i <= NUMTCPMIB; i++) {
- if (Tcp_mib[i].name == NULLCHAR)
- continue;
- tprintf (tstatmib, i, Tcp_mib[i].name,
- Tcp_mib[i].value.integer);
- if (j++ % 2)
- tputs (spaces5);
- else
- tputc ('\n');
- }
- if ((j % 2) == 0)
- tputc ('\n');
-
- return (tstat2 (flag));
- }
-
-
- /* Dump a TCP control block in detail */
- void
- st_tcp (tcb)
- struct tcb *tcb;
- {
- int32 sent, recvd;
-
- if (tcb == NULLTCB)
- return;
-
- rxtx_data_compute (tcb, &sent, &recvd);
-
- tprintf ("Local: %s", pinet (&tcb->conn.local));
- tprintf (" Remote: %s", pinet (&tcb->conn.remote));
- tprintf (" State: %s\n", Tcpstates[(int) tcb->state]);
- tputs (cbheader);
- tprintf (str9lx, tcb->iss);
- tprintf (str9lx, tcb->snd.una);
- tprintf (str9lx, tcb->snd.nxt);
- tprintf ("%7lu", tcb->resent);
- tprintf (str6u, tcb->cwind);
- tprintf (str6u, tcb->ssthresh);
- tprintf (str6u, tcb->snd.wnd);
- tprintf ("%5u", tcb->mss);
- tprintf (str6u, tcb->sndcnt);
- tprintf ("%11lu\n", sent);
-
- tputs ("Recv:");
- tprintf (str9lx, tcb->irs);
- tputs (" ");
- tprintf (str9lx, tcb->rcv.nxt);
- tprintf ("%7lu", tcb->rerecv);
- tputs (spaces6);
- tputs (spaces6);
- tprintf (str6u, tcb->rcv.wnd);
- tputs (spaces5);
- tprintf (str6u, tcb->rcvcnt);
- tprintf ("%11lu\n", recvd);
-
- if (tcb->reseq != (struct reseq *) NULL) {
- register struct reseq *rp;
-
- tputs (reassembly);
- for (rp = tcb->reseq; rp != (struct reseq *) NULL; rp = rp->next) {
- if (tprintf (reassstr, rp->seg.seq, rp->length) == EOF)
- return;
- }
- }
- if (tcb->backoff > 0)
- tprintf (backoffval, tcb->backoff);
- if (tcb->flags.retran)
- tputs (retrying);
- switch (tcb->timer.state) {
- case TIMER_STOP:
- tputs (timerstopped);
- break;
- case TIMER_RUN:
- tprintf (timerrunning,
- (long) read_timer (&tcb->timer),
- (long) dur_timer (&tcb->timer));
- break;
- case TIMER_EXPIRE:
- tputs (timerexp);
- break;
- default:
- break;
- }
- tprintf (rttval, tcb->srtt, tcb->mdev);
- }
-
-
- static void
- rxtx_data_compute (tcb, sent, recvd)
- struct tcb *tcb;
- int32 *sent;
- int32 *recvd;
- {
-
- /* Compute total data sent and received; take out SYN and FIN */
- *sent = tcb->snd.una - tcb->iss; /* Acknowledged data only */
- *recvd = tcb->rcv.nxt - tcb->irs;
- switch (tcb->state) {
- case TCP_LISTEN:
- case TCP_SYN_SENT: /* Nothing received or acked yet */
- *sent = *recvd = 0;
- break;
- case TCP_SYN_RECEIVED:
- (*recvd)--; /* Got SYN, no data acked yet */
- *sent = 0;
- break;
- case TCP_ESTABLISHED: /* Got and sent SYN */
- case TCP_FINWAIT1: /* FIN not acked yet */
- (*sent)--;
- (*recvd)--;
- break;
- case TCP_FINWAIT2: /* Our SYN and FIN both acked */
- *sent -= 2;
- (*recvd)--;
- break;
- case TCP_CLOSE_WAIT: /* Got SYN and FIN, our FIN not yet acked */
- case TCP_CLOSING:
- case TCP_LAST_ACK:
- (*sent)--;
- *recvd -= 2;
- break;
- case TCP_TIME_WAIT: /* Sent and received SYN/FIN, all acked */
- *sent -= 2;
- *recvd -= 2;
- break;
- default:
- break;
- }
- }
-
-
- /* TCP View Command - D. Crompton 1/92 */
- /* Modified for sorted display and */
- /* two views - tcp view b|t - 3/92 */
-
- int
- dotcpview (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- register struct tcb *tcb;
- int32 sent, recvd;
- int i, j, k = 0, vtype;
- char temp[80];
- char *buf, *cp;
-
- if (argc == 1)
- vtype = 1;
- else {
- switch (argv[1][0]) {
- case 'b':
- vtype = 1;
- break;
- case 't':
- vtype = 0;
- break;
- default:
- tputs (viewsyntax);
- return 0;
- }
- }
-
- for (tcb = Tcbs, i = 0; tcb != NULLTCB; tcb = tcb->next) {
- if (tcb->state == TCP_LISTEN)
- continue;
- i++;
- }
-
- if (i) {
- buf = mallocw ((unsigned) (i * 80));
-
- if (vtype)
- tputs (viewhdr1);
- else
- tputs (viewhdr2);
-
- for (tcb = Tcbs, j = 0; tcb != NULLTCB; tcb = tcb->next) {
- if (tcb->state == TCP_LISTEN)
- continue;
-
- strncpy (temp, pinet (&tcb->conn.remote), 80);
- cp = strstr (pinet (&tcb->conn.local), ":");
- if (cp)
- strcat (temp, cp);
- strcat (temp, "/");
- strcat (temp, Tcpstates[(int) tcb->state]);
- temp[37] = 0;
- k = SPRINTF ((&buf[j], "%-35.35s", temp));
- sprintf (temp, "%8lx", ptol (tcb));
- #if 0
- temp[4] = 0;
- k += SPRINTF ((&buf[j + k], " %4s", temp));
- #else
- k += SPRINTF ((&buf[j + k], " %8s", temp));
- #endif
- if (vtype) {
- rxtx_data_compute (tcb, &sent, &recvd);
- k += SPRINTF ((&buf[j + k], "%9lu ", sent));
- k += SPRINTF ((&buf[j + k], "%7lu ", tcb->resent));
- k += SPRINTF ((&buf[j + k], "%9lu ", recvd));
- sprintf (&buf[j + k], "%7lu", tcb->rerecv);
- } else {
- k += SPRINTF ((&buf[j + k], " %4u", tcb->backoff));
- if (tcb->flags.retran)
- k += SPRINTF ((&buf[j + k], viewretrystr));
- else
- k += SPRINTF ((&buf[j + k], viewtrystr));
- switch (tcb->timer.state) {
- case TIMER_STOP:
- k += SPRINTF ((&buf[j + k], viewstopped));
- break;
- case TIMER_RUN:
- k += SPRINTF ((&buf[j + k], viewrun));
- if ((long) dur_timer (&tcb->timer) < 10000) {
- k += SPRINTF ((&buf[j + k], "%ld/%ld)ms",
- (long) read_timer (&tcb->timer),
- (long) dur_timer (&tcb->timer)));
- } else {
- if (((long) read_timer (&tcb->timer) / 1000) > 9999) {
- k += SPRINTF ((&buf[j + k], view9999));
- } else {
- k += SPRINTF ((&buf[j + k], "%ld/%ld)s",
- (long) read_timer (&tcb->timer) / 1000,
- (long) dur_timer (&tcb->timer) / 1000));
- }
- }
- break;
- case TIMER_EXPIRE:
- k += SPRINTF ((&buf[j + k], viewexp));
- break;
- default:
- break;
- }
- for (; k < 73; k++)
- buf[j + k] = ' ';
- if ((tcb->srtt) < 10000)
- sprintf (&buf[j + 73], "%4ldms", tcb->srtt);
- else {
- if ((tcb->srtt / 1000) > 9999) {
- sprintf (&buf[j + 73], ">9999s");
- } else {
- sprintf (&buf[j + 73], "%4lds", tcb->srtt / 1000);
- }
- }
- }
- j += 80;
- }
-
- qsort (buf, (size_t) i, 80, (int (*)(const void *, const void *)) strcmp);
- for (j = 0, k = 0; j < i; j++, k += 80) {
- tputs (&buf[k]);
- if (tputc ('\n') == EOF)
- return 0;
- }
- free (buf);
- }
- return 0;
- }
-
-
- /* tcp timers type - linear v exponential */
- static int
- tcptimer (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- if (argc < 2) {
- tprintf (timeris, *(int *) p ? linearstr : exponentialstr);
- return 0;
- }
- switch (argv[1][0]) {
- case 'l':
- case 'L':
- *(int *) p = 1;
- break;
- case 'e':
- case 'E':
- *(int *) p = 0;
- break;
- default:
- tputs (timertypesyntax);
- return -1;
- }
-
- return 0;
- }
-
-
- static int
- dotcptimer (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
-
- return tcptimer (argc, argv, (void *) &tcptimertype);
- }
-
-
- #if defined(TCPACCESS) || defined(UDPACCESS)
-
- int
- do_tcpudp_access (argc, argv, p)
- int argc;
- char *argv[];
- void *p;
- {
- uint32 target;
- unsigned bits;
- char *bitp;
- int16 lport, hport, state;
- char const *cp; /* for printing the table */
- struct rtaccess *tpacc;
- struct rtaccess **headptr = (struct rtaccess **)p;
- struct rtaccess *head;
- struct rtaccess *prev;
-
- if (argc == 1) { /* print out the table */
- tputs (accesshdr);
- for (tpacc = *headptr; tpacc != NULLACCESS; tpacc = tpacc->nxtbits) {
- if (tpacc->target != 0)
- cp = inet_ntoa (tpacc->target);
- else
- cp = allstr;
- tprintf ("%-16s", cp);
- tprintf ("%4u ", tpacc->bits);
- tprintf ("%9u", tpacc->lowport);
- tprintf ("%10u ", tpacc->highport);
- if (tpacc->status)
- cp = denystr;
- else
- cp = permitstr;
- tprintf ("%-6s\n", cp);
- }
- return 0;
- }
- if (strcmp (argv[1], permitstr) == 0)
- state = 0;
- else {
- if ((strcmp (argv[1], "deny") == 0) || (strcmp (argv[1], "delete") == 0))
- state = (int16) - 1;
- else {
- tputs (accesssyntax);
- return 1;
- }
- }
- if (strcmp (argv[2], allstr) == 0) {
- target = 0;
- bits = 0;
- } else {
- /* If IP address is followed by an optional slash and
- * a length field, (e.g., 128.96/16) get it;
- * otherwise assume a full 32-bit address
- */
- if ((bitp = strchr (argv[2], '/')) != NULLCHAR) {
- /* Terminate address token for resolve() call */
- *bitp++ = '\0';
- bits = (unsigned) atoi (bitp);
- } else
- bits = 32;
-
- if ((target = resolve (argv[2])) == 0) {
- tprintf (Badhost, argv[2]);
- return 1;
- }
- }
-
- if (argc > 3) {
- if (strcmp (argv[3], allstr) == 0) {
- lport = 1;
- hport = 65534L;
- } else {
- lport = (int16) atoi (argv[3]);
- hport = lport;
- }
- } else {
- lport = 0;
- hport = 0;
- }
- if (argc > 4)
- hport = (int16) atoi (argv[4]);
-
- if (strcmp (argv[1], deletestr) == 0) {
- prev = NULLACCESS;
- head = tpacc = *headptr;
- while (tpacc != NULLACCESS) {
- head = tpacc;
- tpacc = tpacc->nxtbits;
- if ((head->target == target) && (head->bits == bits) &&
- (head->lowport == lport) && (head->highport == hport)) { /*match*/
- /*now delete. watch for special cases*/
- if (head == *headptr) /* first in chain */
- *headptr = head->nxtbits;
- else {
- /* sanity check: we cant get here with prev == NULLACCESS !! */
- if (prev)
- prev->nxtbits = tpacc;
- }
- free (head);
- return 0;
- }
- prev = head;
- }
- tputs (notfound);
- return 1;
- }
- /* add the access */
- addtaccess (headptr, target, bits, lport, hport, state);
- return 0;
- }
-
-
-
- static int
- doaccess (argc, argv, p)
- int argc;
- char *argv[];
- void *p OPTIONAL;
- {
- return (do_tcpudp_access (argc, argv, &TCPaccess));
- }
-
-
-
- /*lint -esym(18,addtaccess) */
- /* add an entry to the access control list */
- /* not a lot of error checking 8-) */
- static void
- addtaccess (headacc, target, bits, low, high, permit)
- struct rtaccess **headacc;
- uint32 target; /* Target IP address prefix */
- unsigned int bits; /* Size of target address prefix in bits (0-32) */
- int16 low;
- int16 high;
- int16 permit;
- {
- struct rtaccess *tpacc; /*temporary*/
- struct rtaccess *holder; /*for the new record*/
-
- holder = (struct rtaccess *) callocw (1, sizeof (struct rtaccess));
-
- holder->nxtiface = NULLACCESS;
- holder->nxtbits = NULLACCESS;
- holder->target = target;
- holder->bits = bits;
- holder->lowport = low;
- holder->highport = high;
- holder->status = permit;
-
- if ((low || high) && (*headacc == NULLACCESS || tcp_check (*headacc, target, low) == -1))
- addtaccess (headacc, target, bits, 0, 0, ~permit);
-
- if ((tpacc = *headacc) == NULLACCESS)
- *headacc = holder;
- else {
- while (tpacc->nxtbits != NULLACCESS)
- tpacc = tpacc->nxtbits;
- tpacc->nxtbits = holder;
- }
- }
-
-
-
- /*lint -esym(18,tcp_check) */
- /* check to see if port is "authorized". Returns 0 if matching permit record
- is found or no access records exists, -1 if not found or deny record found */
- int
- tcp_check (accptr, src, port)
- struct rtaccess *accptr;
- uint32 src;
- int16 port;
- {
- unsigned long mask;
- unsigned short tmp;
- int retval = -1;
-
- if (accptr == NULLACCESS)
- return 0; /* no access control */
- for (; accptr != NULLACCESS; accptr = accptr->nxtbits) {
- tmp = (int16) (32 - accptr->bits);
- if (tmp == 32) /* accptr == 0 !! */
- mask = 0; /* GCC bug?? */
- else
- mask = ~0L << tmp; /*lint !e703 */
- if ((accptr->target == (uint32) (mask & src)) &&
- (((port >= accptr->lowport) && (port <= accptr->highport))
- || (!accptr->lowport))) {
- /* if this is a default entry, save the status,
- but look in case there is a more specific entry
- later in the list. If not, upon exit, we will
- return the proper status
- */
- if (!accptr->lowport && !accptr->highport)
- retval = accptr->status;
- else
- return (accptr->status);
- }
- }
- return retval; /* fall through to here if specific entry not found */
- }
-
- #endif
-
-
- /* These are the interface dependent tcp parameters */
- static int doiftcpblimit (int argc, char *argv[], void *p);
- static int doiftcpirtt (int argc, char *argv[], void *p);
- static int doiftcpmaxwait (int argc, char *argv[], void *p);
- static int doiftcpretries (int argc, char *argv[], void *p);
- static int doiftcptimertype (int argc, char *argv[], void *p);
- static int doiftcpwindow (int argc, char *argv[], void *p);
- static int doiftcpsyndata (int argc, char *argv[], void *p);
- static int doiftcpmss (int argc, char *argv[], void *p);
-
-
- static struct cmds Iftcpcmds[] =
- {
- { "blimit", doiftcpblimit, 0, 0, NULLCHAR},
- { "irtt", doiftcpirtt, 0, 0, NULLCHAR},
- { "maxwait", doiftcpmaxwait, 0, 0, NULLCHAR},
- { "mss", doiftcpmss, 0, 0, NULLCHAR},
- { "retries", doiftcpretries, 0, 0, NULLCHAR},
- { "syndata", doiftcpsyndata, 0, 0, NULLCHAR},
- { "timertype", doiftcptimertype, 0, 0, NULLCHAR},
- { "window", doiftcpwindow, 0, 0, NULLCHAR},
- { NULLCHAR, NULL, 0, 0, NULLCHAR}
- };
-
-
- int
- doiftcp (int argc, char *argv[], void *p)
- {
- if (!p)
- return 0;
- return subcmd (Iftcpcmds, argc, argv, p);
- }
-
-
- int
- doiftcpblimit (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpblimit (argc, argv, (void *) &ifp->tcp->blimit);
- }
-
-
- int
- doiftcpirtt (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpirtt (argc, argv, (void *) &ifp->tcp->irtt);
- }
-
-
- int
- doiftcpmaxwait (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpmaxwait (argc, argv, (void *) &ifp->tcp->maxwait);
- }
-
-
- int
- doiftcpmss (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpmss (argc, argv, (void *) &ifp->tcp->mss);
- }
-
-
- int
- doiftcpretries (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpretries (argc, argv, (void *) &ifp->tcp->retries);
- }
-
-
- int
- doiftcptimertype (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcptimer (argc, argv, (void *) &ifp->tcp->timertype);
- }
-
-
- int
- doiftcpwindow (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpwindow (argc, argv, (void *) &ifp->tcp->window);
- }
-
-
- int
- doiftcpsyndata (int argc, char *argv[], void *p)
- {
- struct iface *ifp = p;
-
- return tcpsyndata (argc, argv, (void *) &ifp->tcp->syndata);
- }
-
-
- void
- init_iftcp (struct iftcp *tcp)
- {
- tcp->blimit = Tcp_blimit;
- tcp->maxwait = Tcp_maxwait;
- tcp->window = Tcp_window;
- tcp->mss = Tcp_mss;
- tcp->irtt = Tcp_irtt;
- tcp->retries = Tcp_retries;
- tcp->timertype = tcptimertype;
- tcp->syndata = Tcp_syndata;
- }
-